package net.oschina.bilbodai.common.beanutil.bean.core;

import net.oschina.bilbodai.common.beanutil.bean.AttrPathQueryInfo;
import net.oschina.bilbodai.common.beanutil.bean.type.NullType;
import org.objectweb.asm.Type;

import java.lang.reflect.Field;

/**
 * @author daimao  Date: 16/5/29 Time: 下午10:02
 * @version $Id$
 */
public class PropertyDumpInfo {
    /**
     * 用于源和目标字段映射的唯一名,一般为字段名
     */
    private final String idName;

    private final String profile;

    /**
     * 源属性所在的类的内部名
     */
    private final String srcOwnerInternalName;

    /**
     * 目标属性所在的类的内部名
     */
    private final String targetOwnerInternalName;

    private final boolean dumpOverride;

    private final AttrPathQueryInfo attrPathQueryInfo;

    private final Field srcField;

    private final Field targetField;

    private final String srcFieldInternalName;
    private final String targetFieldInternalName;
    private final String srcGetterName;
    private final String targetGetterName;
    private final String srcSetterName;
    private final String targetSetterName;
    private final String srcGetterDescriptor;
    private final String targetGetterDescriptor;
    private final String srcSetterDescriptor;
    private final String targetSetterDescriptor;

    private final String mapFieldOwnerInternalName;
    private final String mapFieldInternalName;
    private final String mapFieldGetterName;
    private final String mapFieldGetterDescriptor;

    /**
     * 集合类型的实现类型,比如List:(ArrayList,LinkedList)等
     */
    private final Class<?> collectTypeImpl;

    /**
     * 源集合Map的键类型
     */
    private final Class<?> srcKeyType;
    /**
     * 源集合的元素类型, Collection中指元素的类型, Map中指值类型, 一般用于字段没有显示声明泛型的情况
     */
    private final Class<?> srcComponentType;

    /**
     * 目标集合Map的键类型
     */
    private final Class<?> targetKeyType;

    /**
     * 目标集合的元素类型, Collection中指元素的类型, Map中指值类型, 一般用于字段没有显示声明泛型的情况
     */
    private final Class<?> targetComponentType;

    private final boolean sorted;

    public PropertyDumpInfo(String idName, String profile, String srcOwnerInternalName, String targetOwnerInternalName, boolean dumpOverride,
            AttrPathQueryInfo attrPathQueryInfo, Field srcField, Field targetField, String srcFieldInternalName, String targetFieldInternalName,
            String srcGetterName, String targetGetterName,
            String srcSetterName,
            String targetSetterName, String srcGetterDescriptor, String targetGetterDescriptor, String srcSetterDescriptor, String targetSetterDescriptor, String mapFieldOwnerInternalName,
            String mapFieldInternalName, String mapFieldGetterName, String mapFieldGetterDescriptor, Class<?> collectTypeImpl,
            Class<?> srcKeyType, Class<?> srcComponentType, Class<?> targetKeyType, Class<?> targetComponentType, boolean sorted) {
        this.idName = idName;
        this.profile = profile;
        this.srcOwnerInternalName = srcOwnerInternalName;
        this.targetOwnerInternalName = targetOwnerInternalName;
        this.dumpOverride = dumpOverride;
        this.attrPathQueryInfo = attrPathQueryInfo;
        this.srcField = srcField;
        this.targetField = targetField;
        this.srcFieldInternalName = srcFieldInternalName;
        this.targetFieldInternalName = targetFieldInternalName;
        this.srcGetterName = srcGetterName;
        this.targetGetterName = targetGetterName;
        this.srcSetterName = srcSetterName;
        this.targetSetterName = targetSetterName;
        this.srcGetterDescriptor = srcGetterDescriptor;
        this.targetGetterDescriptor = targetGetterDescriptor;
        this.srcSetterDescriptor = srcSetterDescriptor;
        this.targetSetterDescriptor = targetSetterDescriptor;
        this.mapFieldOwnerInternalName = mapFieldOwnerInternalName;
        this.mapFieldInternalName = mapFieldInternalName;
        this.mapFieldGetterName = mapFieldGetterName;
        this.mapFieldGetterDescriptor = mapFieldGetterDescriptor;
        this.collectTypeImpl = collectTypeImpl;
        this.srcKeyType = srcKeyType;
        this.srcComponentType = srcComponentType;
        this.targetKeyType = targetKeyType;
        this.targetComponentType = targetComponentType;
        this.sorted = sorted;
    }

    public boolean isSorted() {
        return sorted;
    }

    public boolean isDumpOverride() {
        return dumpOverride;
    }

    public String getSrcFieldInternalName() {
        return srcFieldInternalName;
    }

    public String getTargetFieldInternalName() {
        return targetFieldInternalName;
    }

    public String getSrcGetterName() {
        return srcGetterName;
    }

    public String getTargetGetterName() {
        return targetGetterName;
    }

    public String getSrcSetterName() {
        return srcSetterName;
    }

    public String getTargetSetterName() {
        return targetSetterName;
    }

    public String getSrcGetterDescriptor() {
        return srcGetterDescriptor;
    }

    public String getTargetGetterDescriptor() {
        return targetGetterDescriptor;
    }

    public String getSrcSetterDescriptor() {
        return srcSetterDescriptor;
    }

    public String getTargetSetterDescriptor() {
        return targetSetterDescriptor;
    }

    public String getIdName() {
        return idName;
    }

    public String getSrcOwnerInternalName() {
        return srcOwnerInternalName;
    }

    public String getTargetOwnerInternalName() {
        return targetOwnerInternalName;
    }

    public Class<?> getCollectTypeImpl() {
        return collectTypeImpl;
    }

    public String getCollectTypeImplInternalName() {
        return Type.getInternalName(getCollectTypeImpl());
    }

    public Class<?> getSrcComponentType() {
        return srcComponentType;
    }

    public Class<?> getTargetComponentType() {
        return targetComponentType;
    }

    public boolean usingCollectTypeImpl() {
        return this.collectTypeImpl != NullType.class;
    }

    public boolean usingAttrPathQuery() {
        return this.attrPathQueryInfo != null;
    }

    public AttrPathQueryInfo getAttrPathQueryInfo() {
        return attrPathQueryInfo;
    }

    public Field getSrcField() {
        return srcField;
    }

    public Field getTargetField() {
        return targetField;
    }

    public Class<?> getSrcKeyType() {
        return srcKeyType;
    }

    public Class<?> getTargetKeyType() {
        return targetKeyType;
    }

    public String getMapFieldOwnerInternalName() {
        return mapFieldOwnerInternalName;
    }

    public String getMapFieldGetterName() {
        return mapFieldGetterName;
    }

    public String getMapFieldGetterDescriptor() {
        return mapFieldGetterDescriptor;
    }

    public String getMapFieldInternalName() {
        return mapFieldInternalName;
    }

    public String getProfile() {
        return profile;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("PropertyDumpInfo{");
        sb.append("idName='").append(idName).append('\'');
        sb.append(", profile='").append(profile).append('\'');
        sb.append(", srcOwnerInternalName='").append(srcOwnerInternalName).append('\'');
        sb.append(", targetOwnerInternalName='").append(targetOwnerInternalName).append('\'');
        sb.append(", dumpOverride=").append(dumpOverride);
        sb.append(", attrPathQueryInfo=").append(attrPathQueryInfo);
        sb.append(", srcField=").append(srcField);
        sb.append(", targetField=").append(targetField);
        sb.append(", srcFieldInternalName='").append(srcFieldInternalName).append('\'');
        sb.append(", targetFieldInternalName='").append(targetFieldInternalName).append('\'');
        sb.append(", srcGetterName='").append(srcGetterName).append('\'');
        sb.append(", targetGetterName='").append(targetGetterName).append('\'');
        sb.append(", srcSetterName='").append(srcSetterName).append('\'');
        sb.append(", targetSetterName='").append(targetSetterName).append('\'');
        sb.append(", srcGetterDescriptor='").append(srcGetterDescriptor).append('\'');
        sb.append(", targetGetterDescriptor='").append(targetGetterDescriptor).append('\'');
        sb.append(", srcSetterDescriptor='").append(srcSetterDescriptor).append('\'');
        sb.append(", targetSetterDescriptor='").append(targetSetterDescriptor).append('\'');
        sb.append(", mapFieldOwnerInternalName='").append(mapFieldOwnerInternalName).append('\'');
        sb.append(", mapFieldInternalName='").append(mapFieldInternalName).append('\'');
        sb.append(", mapFieldGetterName='").append(mapFieldGetterName).append('\'');
        sb.append(", mapFieldGetterDescriptor='").append(mapFieldGetterDescriptor).append('\'');
        sb.append(", collectTypeImpl=").append(collectTypeImpl);
        sb.append(", srcKeyType=").append(srcKeyType);
        sb.append(", srcComponentType=").append(srcComponentType);
        sb.append(", targetKeyType=").append(targetKeyType);
        sb.append(", targetComponentType=").append(targetComponentType);
        sb.append(", sorted=").append(sorted);
        sb.append('}');
        return sb.toString();
    }
}